`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2023/12/10 20:44:40
// Design Name:
// Module Name: Memory
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module Memory(
    input clk,
    input rst,
    input [15:0]in,
    input load,
    input [15:0]address,
    // uart
    input [15:0]uart_in,
    output    load_uart,

    output [15:0]out
  );
  // PARTS:
  // address[14:13]
  // 00/01 => RAM16K 0x0000 ~ 0x3FFF
  // 10 => UART 0x4000~0x4003
  // 0x4000: UART TX Status
  // 0x4001: UART RX Status
  // 0x4002: UART TX Data
  // 0x4003: UART RX Data
  logic [15:0] ram16k['h3FFF:'h0000];
  initial
  begin
    integer i;
    for (i = 0; i <= 'h3FFF; i = i + 1)
    begin
      ram16k[i] = 0;
    end
  end

  // read
  assign out = ((address == 'h4000 || address == 'h4001 || address == 'h4002) ? uart_in
                : (address < 'h4000) ? ram16k[address]
                : 0
               );

  // write
  always @(posedge clk)
  begin
    if (address[14:13] == 2'b00 || address[14:13] == 2'b01)
    begin
      if (load)
      begin
        ram16k[address[13:0]] <= in;
      end
    end
  end

  // write uart
  assign load_uart = (address[14:13] == 2'b10 && address <= 'h4002) ? load : 1'b0;
endmodule
